package geometric3D;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import it.unimi.dsi.fastutil.BidirectionalIterator;
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet;
import it.unimi.dsi.fastutil.objects.ObjectSortedSet;

import Comparator.XYRectangleComparator;
import Comparator.XZRectangleComparator;
import Comparator.YZRectangleComparator;
import Comparator.xLimeSegmentComparator;

public class GeometricOperator {

	public GeometricOperator() {
		super();
	
	}
	
	public static void print (boolean  [][] booleanArray){
		for (int i = 0; i < booleanArray.length; i++) {
			for (int j = 0; j < booleanArray[i].length; j++) {
				System.out.print(booleanArray[i][j]+" ");
			}
			System.out.println("\n");
		}
		
	}
	

	
	
	public static int getEmptySpaceValue(boolean [][] projectedArray, boolean [][] destinationArray, int length){
		int result =0;
		for (int i = 0; i < projectedArray.length; i++) {
			for (int j = 0; j < projectedArray[i].length; j++) {
				if(projectedArray[i][j] && destinationArray[i][j]){
					result+= length;
					projectedArray[i][j] = false;
				}
				
			}
		}
		return result;	
	}
	
	public static boolean [][] fillArray (Rectangle2D projectedRec, List<Rectangle2D> rectangle2dSet){
		boolean [][] result = new boolean [(int)projectedRec.getWidth()][(int)projectedRec.getHeight()];
		for(Rectangle2D currentRectangle2d : rectangle2dSet){
			Rectangle2D intersection  = projectedRec.createIntersection(currentRectangle2d);
			intersection.setRect(intersection.getMinX()-projectedRec.getMinX(), 
					intersection.getMinY()-projectedRec.getMinY(), intersection.getWidth(), intersection.getHeight());
			
			for (int i = (int)intersection.getMinX(); i < (int)intersection.getMaxX(); i++) {
				Arrays.fill(result[i], true);
				
			}
		}
		return result;
		
		
	}
	
	public static int getEmptySpaceValue(YZRectangle yzRectangle , ObjectSortedSet<YZRectangle> yzRectangleSet){
		int result =0;
		Rectangle2D projectedRec2D = yzRectangle.toRectangle2D();
		boolean [][] projectedArray = new boolean [(int)projectedRec2D.getWidth()][(int)projectedRec2D.getHeight()];
		for (int i = 0; i < projectedArray.length; i++) {
			for (int j = 0; j < projectedArray[i].length; j++) {
				projectedArray[i][j] = true;
			}
		}

		do{
			YZRectangle firstYZRectangle = yzRectangleSet.first();
			Point p = new Point(firstYZRectangle.getPosition().getX(),-1 , -1);
			YZRectangle yzSeparate = new  YZRectangle(p, 1, 1, false);
			ObjectSortedSet<YZRectangle> yzOnSurfaceRectangleSet = yzRectangleSet.headSet(yzSeparate);
			List<Rectangle2D> rectangle2dOnSurfaceList = new ArrayList<Rectangle2D>();
			for(YZRectangle currentYZRectangle : yzOnSurfaceRectangleSet){
				rectangle2dOnSurfaceList.add(currentYZRectangle.toRectangle2D());
			}
			boolean [][] destinationArray  = fillArray(projectedRec2D, rectangle2dOnSurfaceList);

			int length = Math.abs(yzRectangle.getPosition().getX() - firstYZRectangle.getPosition().getX());
			result+=getEmptySpaceValue(projectedArray, destinationArray, length);
			yzRectangleSet = yzRectangleSet.tailSet(yzSeparate);
			
		}while(yzRectangleSet.size()>0);
		return result;
	}
	
	public static int getEmptySpaceValue(YZRectangle yzRectangle , ObjectSortedSet<YZRectangle> yzRectangleSet, int xLimit){
//		System.out.println(yzRectangle);
		int result =0;
		Rectangle2D projectedRec2D = yzRectangle.toRectangle2D();
		boolean [][] projectedArray = new boolean [(int)projectedRec2D.getWidth()][(int)projectedRec2D.getHeight()];
		for (int i = 0; i < projectedArray.length; i++) {
			for (int j = 0; j < projectedArray[i].length; j++) {
				projectedArray[i][j] = true;
			}
		}

		while(yzRectangleSet.size()>0){
			YZRectangle firstYZRectangle = yzRectangleSet.first();
			Point p = new Point(firstYZRectangle.getPosition().getX(),-1 , -1);
			YZRectangle yzSeparate = new  YZRectangle(p, 1, 1, false);
			ObjectSortedSet<YZRectangle> yzOnSurfaceRectangleSet = yzRectangleSet.headSet(yzSeparate);
			List<Rectangle2D> rectangle2dOnSurfaceList = new ArrayList<Rectangle2D>();
			for(YZRectangle currentYZRectangle : yzOnSurfaceRectangleSet){
				rectangle2dOnSurfaceList.add(currentYZRectangle.toRectangle2D());
			}
			boolean [][] destinationArray  = fillArray(projectedRec2D, rectangle2dOnSurfaceList);

			int length = Math.abs(yzRectangle.getPosition().getX() - firstYZRectangle.getPosition().getX());
			if(length >= xLimit){
				return result;
				
			}
			result+=getEmptySpaceValue(projectedArray, destinationArray, length);
			yzRectangleSet = yzRectangleSet.tailSet(yzSeparate);
		}
		
		return result;
	}
	
	
	public static int getEmptySpaceValue(XZRectangle xzRectangle , ObjectSortedSet<XZRectangle> xzRectangleSet){
		int result =0;
		Rectangle2D projectedRec2D = xzRectangle.toRectangle2D();
		boolean [][] projectedArray = new boolean [(int)projectedRec2D.getWidth()][(int)projectedRec2D.getHeight()];
		for (int i = 0; i < projectedArray.length; i++) {
			for (int j = 0; j < projectedArray[i].length; j++) {
				projectedArray[i][j] = true;
			}
		}
//		print(projectedArray);
//		System.out.println("---------");
		do{
			XZRectangle firstXZRectangle = xzRectangleSet.first();
			Point p = new Point(-1, firstXZRectangle.getPosition().getY(), -1);
			XZRectangle xzSeparate = new  XZRectangle(p, 1, 1, false);
			ObjectSortedSet<XZRectangle> xzOnSurfaceRectangleSet = xzRectangleSet.headSet(xzSeparate);
			List<Rectangle2D> rectangle2dOnSurfaceList = new ArrayList<Rectangle2D>();
			for(XZRectangle currentXZRectangle : xzOnSurfaceRectangleSet){
				rectangle2dOnSurfaceList.add(currentXZRectangle.toRectangle2D());
			}
			boolean [][] destinationArray  = fillArray(projectedRec2D, rectangle2dOnSurfaceList);
//			print(destinationArray);
			int length = Math.abs(xzRectangle.getPosition().getY() - firstXZRectangle.getPosition().getY());
			result+=getEmptySpaceValue(projectedArray, destinationArray, length);
			xzRectangleSet = xzRectangleSet.tailSet(xzSeparate);
			
		}while(xzRectangleSet.size()>0);
		return result;
	}
	
	
	
	
	
	public static int getEmptySpaceValue(XYRectangle xyRectangle , ObjectSortedSet<XYRectangle> xyRectangleSet){
		Rectangle2D projectedRec2D = xyRectangle.toRectangle2D();
		boolean [][] projectedArray = new boolean [(int)projectedRec2D.getWidth()][(int)projectedRec2D.getHeight()];
		for (int i = 0; i < projectedArray.length; i++) {
			for (int j = 0; j < projectedArray[i].length; j++) {
				projectedArray[i][j] = true;
			}
		}
		int result =0;
		do{
			XYRectangle firstXYRectangle = xyRectangleSet.first();
			Point p = new Point(-1, -1, firstXYRectangle.getPosition().getZ());
			XYRectangle xySeparate = new  XYRectangle(p, 1, 1, false);
			ObjectSortedSet<XYRectangle> xyOnSurfaceRectangleSet = xyRectangleSet.headSet(xySeparate);
			List<Rectangle2D> rectangle2dOnSurfaceList = new ArrayList<Rectangle2D>();
			for(XYRectangle currentXYRectangle : xyOnSurfaceRectangleSet){
				rectangle2dOnSurfaceList.add(currentXYRectangle.toRectangle2D());
			}
			boolean [][] destinationArray  = fillArray(projectedRec2D, rectangle2dOnSurfaceList);
//			print(destinationArray);
			int length = Math.abs(xyRectangle.getPosition().getZ() - firstXYRectangle.getPosition().getZ());
			result+=getEmptySpaceValue(projectedArray, destinationArray, length);
			xyRectangleSet = xyRectangleSet.tailSet(xySeparate);
			
		}while(xyRectangleSet.size()>0);
		
		
		
		
		return result;
		
	}
	
	public static int getEmptySpaceValue(XYRectangle xyRectangle , ObjectSortedSet<XYRectangle> xyRectangleSet, int zLimit){
		Rectangle2D projectedRec2D = xyRectangle.toRectangle2D();
		boolean [][] projectedArray = new boolean [(int)projectedRec2D.getWidth()][(int)projectedRec2D.getHeight()];
		for (int i = 0; i < projectedArray.length; i++) {
			Arrays.fill(projectedArray[i], true);
		}
		int result =0;
		while(xyRectangleSet.size()>0){
			XYRectangle firstXYRectangle = xyRectangleSet.first();
			Point p = new Point(-1, -1, firstXYRectangle.getPosition().getZ());
			XYRectangle xySeparate = new  XYRectangle(p, 1, 1, false);
			ObjectSortedSet<XYRectangle> xyOnSurfaceRectangleSet = xyRectangleSet.headSet(xySeparate);
			List<Rectangle2D> rectangle2dOnSurfaceList = new ArrayList<Rectangle2D>();
			for(XYRectangle currentXYRectangle : xyOnSurfaceRectangleSet){
				rectangle2dOnSurfaceList.add(currentXYRectangle.toRectangle2D());
			}
			boolean [][] destinationArray  = fillArray(projectedRec2D, rectangle2dOnSurfaceList);

			int length = Math.abs(xyRectangle.getPosition().getZ() - firstXYRectangle.getPosition().getZ());
			if(length >= zLimit ){
				return result;
			}
			if(length>0){
				result+=getEmptySpaceValue(projectedArray, destinationArray, length);
			}
			xyRectangleSet = xyRectangleSet.tailSet(xySeparate);
			
		}
		
		
		
		
		return result;
		
	}
	
	
	
	
	
//	private List<EmptySpace> getEmptySpaces(XYRectangle xyRectangle, List<XYRectangle> xyRectangleOnSurfaceList){
//		List<EmptySpace> result = new ArrayList<EmptySpace>();
//		boolean allNonIntersect = true;
//		List<XYRectangle> xyRectangleList = new ArrayList<XYRectangle>();
//		xyRectangleList.add(xyRectangle);
//		List<XYRectangle> leftOverRectangleList;
//		
//		do{
//			
//			
//			
//		}while(!allNonIntersect && xyRectangleList.size()!=0);	
//		for (int i = 0; i < xyRectangleList.size(); i++) {
//			XYRectangle currentXYRectangle = xyRectangleList.get(i);
//			
//			for(XYRectangle currentXYRectangleOnSurface : xyRectangleOnSurfaceList){
//				Rectangle2DRelation
//				relation = GeometricOperator.findRelation(currentXYRectangle, currentXYRectangleOnSurface); 
//				
//				if(relation != Rectangle2DRelation.OUTSIDE && relation != Rectangle2DRelation.TOUCHING ){
//					leftOverRectangleList = currentXYRectangle.getLeftOver(currentXYRectangleOnSurface, relation);
//				
//					XYRectangle overlapedXYRectangle = currentXYRectangle.getOverlaped(currentXYRectangleOnSurface);
//					EmptySpace emptySpace = new EmptySpace(overlapedXYRectangle, 
//							currentXYRectangleOnSurface.getPosition().getZ() - currentXYRectangle.getPosition().getZ());
//					result.add(emptySpace);
//					allNonIntersect = false;
//					break;
//					
//				}
//				
//				
//				
//			}
//			
//			if(!allNonIntersect){
//				List<ArrayList> newXYReArrayLists = leftOverRectangleList.addAll(xyRectangleList.subList(fromIndex, toIndex))
//				break;
//			}	
//			
//		}
//		
//		
//		return null;
//		
//	}
	
//	public static List<EmptySpace> getEmptySpacePositive(XYRectangle xyRectangle, ObjectSortedSet<XYRectangle> xyRectangleSet){
//		xyRectangleSet = GeometricOperator.relatedXYPositive(xyRectangle, xyRectangleSet);
//	
//		List<XYRectangle> currentXYList = new ArrayList<XYRectangle>();
//		List<XYRectangle> updatedXYList = new ArrayList<XYRectangle>();
//		List<EmptySpace> result = new ArrayList<EmptySpace>();
//		currentXYList.add(xyRectangle);
//		boolean endWithCurrentSurface = true;
//		do{
//			
//			updatedXYList = new ArrayList<XYRectangle>();
//			
//			XYRectangle firstXYRectangle = xyRectangleSet.first();
//			Point p = new Point(-1, -1, firstXYRectangle.getPosition().getZ());
//			XYRectangle xySeparate = new XYRectangle(p, 1, 1, false);
//			
//			ObjectSortedSet<XYRectangle> xyOnSurfaceRectangleSet = xyRectangleSet.headSet(xySeparate);
//			xyRectangleSet = xyRectangleSet.tailSet(xySeparate);
//			BidirectionalIterator<XYRectangle> it = xyOnSurfaceRectangleSet.iterator();
//			
//			for(XYRectangle currentXYRectangle : currentXYList){
//				
//				Stack<XYRectangle> stack = new Stack<XYRectangle>();
//				stack.push(currentXYRectangle);
//				
//				for(XYRectangle currentOnSurfaceRectangle : xyOnSurfaceRectangleSet){
//					
//				}
//				
//				
//				
//			}
//			
////			for(XYRectangle currentXYRectangle : currentXYList){
////			while(it.hasNext()){
////				XYRectangle currentXYRectangleOnSurface =it.next();			
////					Rectangle2DRelation
////					relation = GeometricOperator.findRelation(currentXYRectangle, currentXYRectangleOnSurface); 
////					
////					if(relation != Rectangle2DRelation.OUTSIDE && relation != Rectangle2DRelation.TOUCHING ){
////						List<XYRectangle> leftOverRectangleList = currentXYRectangle.getLeftOver(currentXYRectangleOnSurface, relation);
////						updatedXYList.addAll(leftOverRectangleList);
////						XYRectangle overlapedXYRectangle = currentXYRectangle.getOverlaped(currentXYRectangleOnSurface);
////						EmptySpace emptySpace = new EmptySpace(overlapedXYRectangle, 
////								currentXYRectangleOnSurface.getPosition().getZ() - currentXYRectangle.getPosition().getZ());
////						result.add(emptySpace);
////					}else{
////						updatedXYList.add(currentXYRectangle);
////					}
////				}
////				
////			}
//			currentXYList = updatedXYList;
//			
//			
//			
//		}while(updatedXYList.size()!=0 && xyRectangleSet.size()!=0);
//
//		return result;
//		
//	}
	public static ObjectSortedSet<XZRectangle> relatedXZPositive(XZRectangle xzRectangle, ObjectSortedSet<XZRectangle> xzRectangleSortedSet){
		ObjectSortedSet<XZRectangle> result = new ObjectRBTreeSet<XZRectangle>(new XZRectangleComparator(true));
		Point p=  new Point(xzRectangle.getMaxX(),xzRectangle.getPosition().getY(), xzRectangle.getMaxZ());
		XZRectangle seperateRectangle = new XZRectangle(p, 1, 1, false);
		xzRectangleSortedSet = xzRectangleSortedSet.tailSet(seperateRectangle);
//		System.out.println(xzRectangleSortedSet);
		BidirectionalIterator<XZRectangle> it = xzRectangleSortedSet.iterator();		
		while(it.hasNext()){
			XZRectangle currentXZRectangle = it.next();
			Rectangle2DRelation relation = findRelation(xzRectangle, currentXZRectangle);
			if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
				
			}else{
				result.add(currentXZRectangle);
			}
				
			
		}
		return result;
	}
	
	public static XZRectangle closestXZPositive(XZRectangle xzRectangle, ObjectSortedSet<XZRectangle> xzRectangleSortedSet){
		
		Point p=  new Point(xzRectangle.getMaxX(),xzRectangle.getPosition().getY(), xzRectangle.getMaxZ());
		XZRectangle seperateRectangle = new XZRectangle(p, 1, 1, false);
		xzRectangleSortedSet = xzRectangleSortedSet.tailSet(seperateRectangle);
//		System.out.println(xzRectangleSortedSet);
		BidirectionalIterator<XZRectangle> it = xzRectangleSortedSet.iterator();	
		boolean foundClosest = false;
		XZRectangle currentXZRectangle =null;
		while(it.hasNext() && !foundClosest){
			currentXZRectangle = it.next();
			Rectangle2DRelation relation = findRelation(xzRectangle, currentXZRectangle);
			if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
				return currentXZRectangle;
			}
				
			
		}
		return null;
	}
	
	public static ObjectSortedSet<XZRectangle> touchingXZPositive(XZRectangle xzRectangle, ObjectSortedSet<XZRectangle> xzRectangleSortedSet){
		ObjectSortedSet<XZRectangle> result = new ObjectRBTreeSet<XZRectangle>(new XZRectangleComparator(true));
		Point p=  new Point(xzRectangle.getMaxX(),xzRectangle.getPosition().getY(), xzRectangle.getMaxZ());
		XZRectangle seperateRectangle = new XZRectangle(p, 1, 1, false);
		xzRectangleSortedSet = xzRectangleSortedSet.tailSet(seperateRectangle);
//		System.out.println(xzRectangleSortedSet);
		BidirectionalIterator<XZRectangle> it = xzRectangleSortedSet.iterator();
		boolean stillTouching = true;
		while(it.hasNext() && stillTouching){
			
			XZRectangle currentXZRectangle = it.next();
			if(currentXZRectangle.getPosition().getY() == xzRectangle.getPosition().getY()){
				Rectangle2DRelation relation = findRelation(xzRectangle, currentXZRectangle);
				if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
					
				}else{
					result.add(currentXZRectangle);
				}
			}else{
				stillTouching = false;
			}
				
			
		}
		return result;
	}
	public static ObjectSortedSet<XZRectangle> relatedXZNegative(XZRectangle xzRectangle, ObjectSortedSet<XZRectangle> xzRectangleSortedSet){
		ObjectSortedSet<XZRectangle> result = new ObjectRBTreeSet<XZRectangle>(new XZRectangleComparator(false));
		Point p=  new Point(xzRectangle.getMaxX(),xzRectangle.getPosition().getY(), xzRectangle.getMaxZ());
		XZRectangle seperateRectangle = new XZRectangle(p, 1, 1, true);
		xzRectangleSortedSet = xzRectangleSortedSet.tailSet(seperateRectangle);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XZRectangle> it = xzRectangleSortedSet.iterator();		
		while(it.hasNext()){
			XZRectangle currentXZRectangle = it.next();
			Rectangle2DRelation relation = findRelation(xzRectangle, currentXZRectangle);
			if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
				
			}else{
				result.add(currentXZRectangle);
			}
				
			
		}
		return result;
	}
	
	public static XZRectangle closestXZNegative(XZRectangle xzRectangle, ObjectSortedSet<XZRectangle> xzRectangleSortedSet){
		
		Point p=  new Point(xzRectangle.getMaxX(),xzRectangle.getPosition().getY(), xzRectangle.getMaxZ());
		XZRectangle seperateRectangle = new XZRectangle(p, 1, 1, true);
		xzRectangleSortedSet = xzRectangleSortedSet.tailSet(seperateRectangle);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XZRectangle> it = xzRectangleSortedSet.iterator();
		boolean foundClosest = false;
		XZRectangle currentXZRectangle = null;
		while(it.hasNext() && !foundClosest){
			currentXZRectangle= it.next();
			Rectangle2DRelation relation = findRelation(xzRectangle, currentXZRectangle);
			if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
				
				return currentXZRectangle;
			}
				
			
		}
		return null;
	}
	
	
	public static ObjectSortedSet<XZRectangle> touchingXZNegative(XZRectangle xzRectangle, ObjectSortedSet<XZRectangle> xzRectangleSortedSet){
		ObjectSortedSet<XZRectangle> result = new ObjectRBTreeSet<XZRectangle>(new XZRectangleComparator(false));
		Point p=  new Point(xzRectangle.getMaxX(),xzRectangle.getPosition().getY(), xzRectangle.getMaxZ());
		XZRectangle yzRectangle1 = new XZRectangle(p, 1, 1, true);
		xzRectangleSortedSet = xzRectangleSortedSet.tailSet(yzRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XZRectangle> it = xzRectangleSortedSet.iterator();	
		boolean stillTouching = true;
		while(it.hasNext() && stillTouching){
			XZRectangle currentXZRectangle = it.next();
			if(currentXZRectangle.getPosition().getY() == xzRectangle.getPosition().getY()){
				Rectangle2DRelation relation = findRelation(xzRectangle, currentXZRectangle);
				if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
					
				}else{
					result.add(currentXZRectangle);
				}
			}else{
				stillTouching= false;
			}
				
			
		}
		return result;
	}
	
	public static ObjectSortedSet<YZRectangle> relatedYZPositive(YZRectangle yzRectangle, ObjectSortedSet<YZRectangle> yzRectangleSortedSet){
		ObjectSortedSet<YZRectangle> result = new ObjectRBTreeSet<YZRectangle>(new YZRectangleComparator(true));
		Point p=  new Point(yzRectangle.getPosition().getX(), yzRectangle.getMaxY(), yzRectangle.getMaxZ());
		YZRectangle yzRectangle1 = new YZRectangle(p, 1, 1, false);
		yzRectangleSortedSet = yzRectangleSortedSet.tailSet(yzRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<YZRectangle> it = yzRectangleSortedSet.iterator();		
		while(it.hasNext()){
			YZRectangle currentYZRectangle = it.next();
			Rectangle2DRelation relation = findRelation(yzRectangle, currentYZRectangle);
			if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
				
			}else{
				result.add(currentYZRectangle);
			}
				
			
		}
		return result;
	}
	
	public static YZRectangle closestYZPositive(YZRectangle yzRectangle, ObjectSortedSet<YZRectangle> yzRectangleSortedSet){
		
		Point p=  new Point(yzRectangle.getPosition().getX(), yzRectangle.getMaxY(), yzRectangle.getMaxZ());
		YZRectangle yzRectangle1 = new YZRectangle(p, 1, 1, false);
		yzRectangleSortedSet = yzRectangleSortedSet.tailSet(yzRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<YZRectangle> it = yzRectangleSortedSet.iterator();	
		boolean foundClosest = false;
		while(it.hasNext() && !foundClosest){
			YZRectangle currentYZRectangle = it.next();
			Rectangle2DRelation relation = findRelation(yzRectangle, currentYZRectangle);
			if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
				

//				result.add(currentYZRectangle);
				return currentYZRectangle;
			}
				
			
		}
		return null;
	}
	
	public static ObjectSortedSet<YZRectangle> closestYZPositive(YZRectangle yzRectangle, ObjectSortedSet<YZRectangle> yzRectangleSortedSet, int xLimit){
		ObjectSortedSet<YZRectangle> result = new ObjectRBTreeSet<YZRectangle>(new YZRectangleComparator(true));
		Point p=  new Point(yzRectangle.getPosition().getX(), yzRectangle.getMaxY(), yzRectangle.getMaxZ());
		YZRectangle seperateRectangle = new YZRectangle(p, 1, 1, false);
		yzRectangleSortedSet = yzRectangleSortedSet.tailSet(seperateRectangle);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<YZRectangle> it = yzRectangleSortedSet.iterator();	
		boolean outsideLimit = false;
		while(it.hasNext() && !outsideLimit){
			YZRectangle currentYZRectangle = it.next();
			if(currentYZRectangle.getPosition().getX() - yzRectangle.getPosition().getX() < xLimit){	
				Rectangle2DRelation relation = findRelation(yzRectangle, currentYZRectangle);
			
				if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
					result.add(currentYZRectangle);
	//				return currentYZRectangle;
				}
			}else{
				outsideLimit = true;
			}
				
			
		}
		return result;
	}
	
	public static ObjectSortedSet<YZRectangle> touchingYZPositive(YZRectangle yzRectangle, ObjectSortedSet<YZRectangle> yzRectangleSortedSet){
		ObjectSortedSet<YZRectangle> result = new ObjectRBTreeSet<YZRectangle>(new YZRectangleComparator(true));
		Point p=  new Point(yzRectangle.getPosition().getX(), yzRectangle.getMaxY(), yzRectangle.getMaxZ());
		YZRectangle yzRectangle1 = new YZRectangle(p, 1, 1, false);
		yzRectangleSortedSet = yzRectangleSortedSet.tailSet(yzRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<YZRectangle> it = yzRectangleSortedSet.iterator();
		boolean stillTouching = true;
		while(it.hasNext() && stillTouching){
			YZRectangle currentYZRectangle = it.next();
			if(currentYZRectangle.getPosition().getX()== yzRectangle.getPosition().getX()){
				Rectangle2DRelation relation = findRelation(yzRectangle, currentYZRectangle);
				if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
					result.add(currentYZRectangle);
				}
			}else{
				stillTouching= false;
			}
				
			
		}
		return result;
	}
	
	public static ObjectSortedSet<YZRectangle> relatedYZNegative(YZRectangle yzRectangle, ObjectSortedSet<YZRectangle> yzRectangleSortedSet){
		ObjectSortedSet<YZRectangle> result = new ObjectRBTreeSet<YZRectangle>(new YZRectangleComparator(false));
		Point p=  new Point(yzRectangle.getPosition().getX(), yzRectangle.getMaxY(), yzRectangle.getMaxZ());
		YZRectangle yzRectangle1 = new YZRectangle(p, 1, 1, true);
		yzRectangleSortedSet = yzRectangleSortedSet.tailSet(yzRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<YZRectangle> it = yzRectangleSortedSet.iterator();		
		while(it.hasNext()){
			YZRectangle currentXYRectangle = it.next();
			Rectangle2DRelation relation = findRelation(yzRectangle, currentXYRectangle);
			if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
				
			}else{
				result.add(currentXYRectangle);
			}
				
			
		}
		return result;
	}
	
	public static YZRectangle closestYZNegative(YZRectangle yzRectangle, ObjectSortedSet<YZRectangle> yzRectangleSortedSet) {
		
		Point p=  new Point(yzRectangle.getPosition().getX(), yzRectangle.getMaxY(), yzRectangle.getMaxZ());
		YZRectangle yzRectangle1 = new YZRectangle(p, 1, 1, true);
		yzRectangleSortedSet = yzRectangleSortedSet.tailSet(yzRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<YZRectangle> it = yzRectangleSortedSet.iterator();	
		boolean foundClosest = false;
		while(it.hasNext() && !foundClosest){
			YZRectangle currentXYRectangle = it.next();
			Rectangle2DRelation relation = findRelation(yzRectangle, currentXYRectangle);
			if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
//				result.add(currentXYRectangle);
				return currentXYRectangle;
			}
				
			
		}
		return null;

		
	}
	
	
	public static ObjectSortedSet<YZRectangle> closestYZNegative(YZRectangle yzRectangle, ObjectSortedSet<YZRectangle> yzRectangleSortedSet, int xLimit) {
		ObjectSortedSet<YZRectangle> result = new ObjectRBTreeSet<YZRectangle>(new YZRectangleComparator(false));
		Point p=  new Point(yzRectangle.getPosition().getX(), yzRectangle.getMaxY(), yzRectangle.getMaxZ());
		YZRectangle yzRectangle1 = new YZRectangle(p, 1, 1, true);
		yzRectangleSortedSet = yzRectangleSortedSet.tailSet(yzRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<YZRectangle> it = yzRectangleSortedSet.iterator();	
		boolean outsideLimit = false;
		while(it.hasNext() && !outsideLimit){
			YZRectangle currentXYRectangle = it.next();
			if(yzRectangle.getPosition().getX() - currentXYRectangle.getPosition().getX() < xLimit){
				Rectangle2DRelation relation = findRelation(yzRectangle, currentXYRectangle);
				if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
					result.add(currentXYRectangle);
//					
				}
			}else{
				outsideLimit= true;
			}
				
			
		}
		return result;

		
	}
	
	
	
	
	
	public static ObjectSortedSet<YZRectangle> touchingYZNegative(YZRectangle yzRectangle, ObjectSortedSet<YZRectangle> yzRectangleSortedSet){
		ObjectSortedSet<YZRectangle> result = new ObjectRBTreeSet<YZRectangle>(new YZRectangleComparator(false));
		Point p=  new Point(yzRectangle.getPosition().getX(), yzRectangle.getMaxY(), yzRectangle.getMaxZ());
		YZRectangle yzRectangle1 = new YZRectangle(p, 1, 1, true);
		yzRectangleSortedSet = yzRectangleSortedSet.tailSet(yzRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<YZRectangle> it = yzRectangleSortedSet.iterator();		
		boolean stillTouching = true;
		while(it.hasNext() && stillTouching){
			YZRectangle currentYZRectangle = it.next();
			if(currentYZRectangle.getPosition().getX() == yzRectangle.getPosition().getX()){
				Rectangle2DRelation relation = findRelation(yzRectangle, currentYZRectangle);
				if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
					result.add(currentYZRectangle);
				}
			}else{
				stillTouching= false;
			}
				
			
		}
		return result;
	}
	
	
	public static ObjectSortedSet<XYRectangle> relatedXYPositive(XYRectangle xyRectangle, ObjectSortedSet<XYRectangle> xyRectangleSortedSet){
		ObjectSortedSet<XYRectangle> result = new ObjectRBTreeSet<XYRectangle>(new XYRectangleComparator(true));
		Point p=  new Point(xyRectangle.getMaxX(), xyRectangle.getMaxY(), xyRectangle.getPosition().getZ());
		XYRectangle xyRectangle1 = new XYRectangle(p, 1, 1, false);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xyRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();		
		while(it.hasNext()){
			XYRectangle currentXYRectangle = it.next();
			Rectangle2DRelation relation = findRelation(xyRectangle, currentXYRectangle);
			if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
				
			}else{
				result.add(currentXYRectangle);
			}
				
			
		}
		return result;
		
	}
	
	
	
	public static XYRectangle closestXYPositive(XYRectangle xyRectangle, ObjectSortedSet<XYRectangle> xyRectangleSortedSet){
		
		
		Point p=  new Point(xyRectangle.getMaxX(), xyRectangle.getMaxY(), xyRectangle.getPosition().getZ());
		XYRectangle xyRectangle1 = new XYRectangle(p, 1, 1, false);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xyRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();	
		boolean foundClosest = false;
		XYRectangle currentXYRectangle =null;
		while(it.hasNext() &&!foundClosest){
			currentXYRectangle = it.next();
			Rectangle2DRelation relation = findRelation(xyRectangle, currentXYRectangle);
			if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
				return currentXYRectangle;
			}
				
			
		}
		return null;
	}
	
public static ObjectSortedSet<XYRectangle> closestXYPositive(XYRectangle xyRectangle, ObjectSortedSet<XYRectangle> xyRectangleSortedSet, int zLimit){
		
		ObjectSortedSet<XYRectangle> result = new ObjectRBTreeSet<XYRectangle>(new XYRectangleComparator(true));
		Point p=  new Point(xyRectangle.getMaxX(), xyRectangle.getMaxY(), xyRectangle.getPosition().getZ());
		XYRectangle xyRectangle1 = new XYRectangle(p, 1, 1, false);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xyRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();	
		boolean outsideLimit = false;
		XYRectangle currentXYRectangle =null;
		while(it.hasNext() &&!outsideLimit){
			currentXYRectangle = it.next();
			if(currentXYRectangle.getPosition().getZ() - xyRectangle.getPosition().getZ() <zLimit){
				Rectangle2DRelation relation = findRelation(xyRectangle, currentXYRectangle);
				if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
					result.add(currentXYRectangle);
				}
			}else{
				outsideLimit = true;
			}
				
			
		}
		return result;
	}
	
	public static ObjectSortedSet<XYRectangle> touchingXYPositive(XYRectangle xyRectangle, ObjectSortedSet<XYRectangle> xyRectangleSortedSet){
		ObjectSortedSet<XYRectangle> result = new ObjectRBTreeSet<XYRectangle>(new XYRectangleComparator(true));
		Point p=  new Point(xyRectangle.getMaxX(), xyRectangle.getMaxY(), xyRectangle.getPosition().getZ());
		XYRectangle xyRectangle1 = new XYRectangle(p, 1, 1, false);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xyRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();
		boolean stillTouching = true;
		while(it.hasNext() && stillTouching){
			XYRectangle currentXYRectangle = it.next();
			if(currentXYRectangle.getPosition().getZ() == xyRectangle.getPosition().getZ()){
				Rectangle2DRelation relation = findRelation(xyRectangle, currentXYRectangle);
				if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
					
				}else{
					result.add(currentXYRectangle);
				}
			}else{
				stillTouching = false;
			}
				
			
		}
		return result;
		
	}
	
	public static Rectangle2DRelation findRelation(YZRectangle yzRectangle1, YZRectangle yzRectangle2){
		Rectangle2D this2D = yzRectangle1.toRectangle2D();
		Rectangle2D xyRectangle2D = yzRectangle2.toRectangle2D();
		
		if(xyRectangle2D.contains(this2D))return Rectangle2DRelation.INSIDE;
		if(this2D.contains(xyRectangle2D)) return Rectangle2DRelation.CONTAIN;
		if((yzRectangle1.getMinY() == yzRectangle2.getMaxY()
				|| yzRectangle1.getMaxY() == yzRectangle2.getMinY())
				&& (yzRectangle2.getMinZ() <= yzRectangle1.getMaxZ()  
						&& yzRectangle2.getMinZ() >= yzRectangle1.getMinZ() 
					||yzRectangle2.getMaxZ() <= yzRectangle1.getMaxZ()  
						&& yzRectangle2.getMaxZ() >= yzRectangle1.getMinZ())){
			return Rectangle2DRelation.TOUCHING;
		}else if((yzRectangle1.getMinZ() == yzRectangle2.getMaxZ()
				|| yzRectangle1.getMaxZ() == yzRectangle2.getMinZ())
				&& ((yzRectangle2.getMinY() <= yzRectangle1.getMaxY()  
						&& yzRectangle2.getMinY() >= yzRectangle1.getMinY()) 
					||(yzRectangle2.getMaxY() <= yzRectangle1.getMaxY()  
						&& yzRectangle2.getMaxY() >= yzRectangle1.getMinY()))){
			return Rectangle2DRelation.TOUCHING;
		}else if(this2D.intersects(xyRectangle2D)){
			int pointContain =0 ;
//			System.out.println(this.getPoint2D());
//			System.out.println(xyRectangle.getPoint2D());
			for(Point2D p2D : yzRectangle2.getPoint2D()){
				if(this2D.contains(p2D)){
//					System.out.println(p2D);
					pointContain++;
				}
				
			}
			if(pointContain==0){
				return Rectangle2DRelation.ZEROINSIDE;
			}else if(pointContain==1){
				return Rectangle2DRelation.ONEINSIDE;
			}else if(pointContain==2){
				return Rectangle2DRelation.TWOINSIDE;
			}
			
		}
		return Rectangle2DRelation.OUTSIDE;
	}
	
	
	public static Rectangle2DRelation findRelation(XZRectangle xzRectangle1, XZRectangle xzRectangle2){
		Rectangle2D this2D = xzRectangle1.toRectangle2D();
		Rectangle2D xyRectangle2D = xzRectangle2.toRectangle2D();
		
		if(xyRectangle2D.contains(this2D))return Rectangle2DRelation.INSIDE;
		if(this2D.contains(xyRectangle2D)) return Rectangle2DRelation.CONTAIN;
		if((xzRectangle1.getMinX() == xzRectangle2.getMaxX()
				|| xzRectangle1.getMaxX() == xzRectangle2.getMinX())
				&& (xzRectangle2.getMinZ() <= xzRectangle1.getMaxZ()  
						&& xzRectangle2.getMinZ() >= xzRectangle1.getMinZ() 
					||xzRectangle2.getMaxZ() <= xzRectangle1.getMaxZ()  
						&& xzRectangle2.getMaxZ() >= xzRectangle1.getMinZ())){
			return Rectangle2DRelation.TOUCHING;
		}else if((xzRectangle1.getMinZ() == xzRectangle2.getMaxZ()
				|| xzRectangle1.getMaxZ() == xzRectangle2.getMinZ())
				&& ((xzRectangle2.getMinX() <= xzRectangle1.getMaxX()  
						&& xzRectangle2.getMinX() >= xzRectangle1.getMinX()) 
					||(xzRectangle2.getMaxX() <= xzRectangle1.getMaxX()  
						&& xzRectangle2.getMaxX() >= xzRectangle1.getMinX()))){
			return Rectangle2DRelation.TOUCHING;
		}else if(this2D.intersects(xyRectangle2D)){
			int pointContain =0 ;
//			System.out.println(this.getPoint2D());
//			System.out.println(xyRectangle.getPoint2D());
			for(Point2D p2D : xzRectangle2.getPoint2D()){
				if(this2D.contains(p2D)){
//					System.out.println(p2D);
					pointContain++;
				}
				
			}
			if(pointContain==0){
				return Rectangle2DRelation.ZEROINSIDE;
			}else if(pointContain==1){
				return Rectangle2DRelation.ONEINSIDE;
			}else if(pointContain==2){
				return Rectangle2DRelation.TWOINSIDE;
			}
			
		}
		return Rectangle2DRelation.OUTSIDE;
		
	}
	
	public static Rectangle2DRelation findRelation(XYRectangle xyRectangle1, XYRectangle xyRectangle2){
		Rectangle2D this2D = xyRectangle1.toRectangle2D();
		Rectangle2D xyRectangle2D = xyRectangle2.toRectangle2D();
		
		if(xyRectangle2D.contains(this2D))return Rectangle2DRelation.INSIDE;
		if(this2D.contains(xyRectangle2D)) return Rectangle2DRelation.CONTAIN;
		if((xyRectangle1.getMinX() == xyRectangle2.getMaxX()
				|| xyRectangle1.getMaxX() == xyRectangle2.getMinX())
				&& (xyRectangle2.getMinY() <= xyRectangle1.getMaxY()  
						&& xyRectangle2.getMinY() >= xyRectangle1.getMinY() 
					||xyRectangle2.getMaxY() <= xyRectangle1.getMaxY()  
						&& xyRectangle2.getMaxY() >= xyRectangle1.getMinY())){
			return Rectangle2DRelation.TOUCHING;
		}else if((xyRectangle1.getMinY() == xyRectangle2.getMaxY()
				|| xyRectangle1.getMaxY() == xyRectangle2.getMinY())
				&& ((xyRectangle2.getMinX() <= xyRectangle1.getMaxX()  
						&& xyRectangle2.getMinX() >= xyRectangle1.getMinX()) 
					||(xyRectangle2.getMaxX() <= xyRectangle1.getMaxX()  
						&& xyRectangle2.getMaxX() >= xyRectangle1.getMinX()))){
			return Rectangle2DRelation.TOUCHING;
		}else if(this2D.intersects(xyRectangle2D)){
			int pointContain =0 ;
//			System.out.println(this.getPoint2D());
//			System.out.println(xyRectangle.getPoint2D());
			for(Point2D p2D : xyRectangle2.getPoint2D()){
				if(this2D.contains(p2D)){
//					System.out.println(p2D);
					pointContain++;
				}
				
			}
			if(pointContain==0){
				return Rectangle2DRelation.ZEROINSIDE;
			}else if(pointContain==1){
				return Rectangle2DRelation.ONEINSIDE;
			}else if(pointContain==2){
				return Rectangle2DRelation.TWOINSIDE;
			}
			
		}
		return Rectangle2DRelation.OUTSIDE;
	}
	
	/**
	 * return related xyRectangle in the negative way
	 * @param xyRectangle
	 * @param xyRectangleSortedSet
	 * @return
	 */
	public static ObjectSortedSet<XYRectangle> relatedXYNegative(XYRectangle xyRectangle, ObjectSortedSet<XYRectangle> xyRectangleSortedSet){
		ObjectSortedSet<XYRectangle> result = new ObjectRBTreeSet<XYRectangle>(new XYRectangleComparator(false));
		Point p=  new Point(xyRectangle.getMaxX(), xyRectangle.getMaxY(), xyRectangle.getPosition().getZ());
		XYRectangle xyRectangle1 = new XYRectangle(p, 1, 1, true);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xyRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();		
		while(it.hasNext()){
			XYRectangle currentXYRectangle = it.next();
			Rectangle2DRelation relation = findRelation(xyRectangle, currentXYRectangle);
			if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
				
			}else{
				result.add(currentXYRectangle);
			}
				
			
		}
		return result;
		
	}
	
	public static XYRectangle closestXYNegative(XYRectangle xyRectangle, ObjectSortedSet<XYRectangle> xyRectangleSortedSet){
		
		
		Point p=  new Point(xyRectangle.getMaxX(), xyRectangle.getMaxY(), xyRectangle.getPosition().getZ());
		XYRectangle xyRectangle1 = new XYRectangle(p, 1, 1, true);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xyRectangle1);

		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();		
		boolean foundClosest = false;
		XYRectangle currentXYRectangle =null;
		while(it.hasNext() && !foundClosest){
			currentXYRectangle = it.next();
			Rectangle2DRelation relation = findRelation(xyRectangle, currentXYRectangle);
			if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
				
				return currentXYRectangle;
			}
				
			
		}
		return null;
		
//		System.out.println(xyRectangleSortedSet);
		
		
	
	}
	
	public static ObjectSortedSet<XYRectangle> closestXYNegative(XYRectangle xyRectangle, ObjectSortedSet<XYRectangle> xyRectangleSortedSet, int zLimit){
		
		ObjectSortedSet<XYRectangle> result = new ObjectRBTreeSet<XYRectangle>(new XYRectangleComparator(false));
		Point p=  new Point(xyRectangle.getMaxX(), xyRectangle.getMaxY(), xyRectangle.getPosition().getZ());
		XYRectangle xyRectangle1 = new XYRectangle(p, 1, 1, true);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xyRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();		
		boolean outsideLimit = false;
		XYRectangle currentXYRectangle =null;
		while(it.hasNext() && !outsideLimit){
			currentXYRectangle = it.next();
			
			if(xyRectangle.getPosition().getZ() - currentXYRectangle.getPosition().getZ() < zLimit){
				Rectangle2DRelation relation = findRelation(xyRectangle, currentXYRectangle);
				if(!(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING)){
					result.add(currentXYRectangle);
				}
			}else{
				outsideLimit = true;
			}
			
				
			
		}
		return result;

	
	}
	
	public static ObjectSortedSet<XYRectangle> touchingXYNegative(XYRectangle xyRectangle, ObjectSortedSet<XYRectangle> xyRectangleSortedSet){
		ObjectSortedSet<XYRectangle> result = new ObjectRBTreeSet<XYRectangle>(new XYRectangleComparator(false));
		Point p=  new Point(xyRectangle.getMaxX(), xyRectangle.getMaxY(), xyRectangle.getPosition().getZ());
		XYRectangle xyRectangle1 = new XYRectangle(p, 1, 1, true);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xyRectangle1);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();
		boolean stillTouching = true;
		while(it.hasNext() && stillTouching ){
			XYRectangle currentXYRectangle = it.next();
			if(xyRectangle.getPosition().getZ() == currentXYRectangle.getPosition().getZ()){
				Rectangle2DRelation relation = findRelation(xyRectangle, currentXYRectangle);
				if(relation == Rectangle2DRelation.OUTSIDE || relation == Rectangle2DRelation.TOUCHING){
					
				}else{
					result.add(currentXYRectangle);
				}
			}else{
				stillTouching = false;
			}
			
		}
		return result;
		
	}
	
	
	public static Point projectXPositive(Point p, ObjectSortedSet<YZRectangle> yzRectangleSortedSet, boolean includeTouching, int maxX){
		YZRectangle yzRectangle = new YZRectangle(p, 1, 1, false);
		xLineSegment xLineSegment = new xLineSegment(p, 1000, true);
		yzRectangleSortedSet = yzRectangleSortedSet.tailSet(yzRectangle);
//		System.out.println(yzRectangleSortedSet);
		BidirectionalIterator<YZRectangle> it = yzRectangleSortedSet.iterator();		
		while(it.hasNext()){
			YZRectangle currentYZRectangle = it.next();
			RectangleLineRelation relation = findRelation(currentYZRectangle, xLineSegment);
			if(includeTouching){
				if(relation == RectangleLineRelation.TOUCHING || relation == RectangleLineRelation.INTERSECT){
					return intersection(currentYZRectangle, xLineSegment);
				}
			}else{
				if(relation == RectangleLineRelation.INTERSECT){
					return intersection(currentYZRectangle, xLineSegment);
				}
			}
			
		}
		return new Point(maxX, p.getY(), p.getZ());
	}
	
	
	public static Point projectXNegative(Point p, ObjectSortedSet<YZRectangle> yzObjectSortedSet, boolean includeTouching){
		YZRectangle yzRectangle = new YZRectangle(p, 1, 1, true);
		xLineSegment xLineSegment = new xLineSegment(p, 1000, false);
		yzObjectSortedSet = yzObjectSortedSet.tailSet(yzRectangle);
//		System.out.println(yzObjectSortedSet);
		BidirectionalIterator<YZRectangle> it = yzObjectSortedSet.iterator();		
		while(it.hasNext()){
			YZRectangle currentYZRectangle = it.next();
			RectangleLineRelation relation = findRelation(currentYZRectangle, xLineSegment);
			if(includeTouching){
				if(relation == RectangleLineRelation.TOUCHING || relation == RectangleLineRelation.INTERSECT){
					return intersection(currentYZRectangle, xLineSegment);
				}
			}else{
				if(relation == RectangleLineRelation.INTERSECT){
					return intersection(currentYZRectangle, xLineSegment);
				}
			}	
		}
		return new Point(0,p.getY(),p.getZ());
	} 
	public static Point projectYPositive(Point p, ObjectSortedSet<XZRectangle> xzRectangleSortedSet, boolean includeTouching, int maxY){
		XZRectangle xzRectangle = new XZRectangle(p, 1, 1, false);
		yLineSegment yLineSegment = new yLineSegment(p, 1000, true);
		xzRectangleSortedSet = xzRectangleSortedSet.tailSet(xzRectangle);
//		System.out.println(xzRectangleSortedSet);
		BidirectionalIterator<XZRectangle> it = xzRectangleSortedSet.iterator();		
		while(it.hasNext()){
			XZRectangle currentXZRectangle = it.next();
			RectangleLineRelation relation = findRelation(currentXZRectangle, yLineSegment);
			if(includeTouching){
				if(relation == RectangleLineRelation.TOUCHING || relation == RectangleLineRelation.INTERSECT){
					return intersection(currentXZRectangle, yLineSegment);
				}
			}else{
				if(relation == RectangleLineRelation.INTERSECT){
					return intersection(currentXZRectangle, yLineSegment);
				}
			}
			
		}
		return new Point(p.getX(), maxY, p.getZ());
	} 
	
	public static Point projectYNegative(Point p, ObjectSortedSet<XZRectangle> xzRectangleSortedSet, boolean includeTouching){
		XZRectangle xzRectangle = new XZRectangle(p, 1, 1, true);
		yLineSegment yLineSegment = new yLineSegment(p, 1000, false);
		xzRectangleSortedSet = xzRectangleSortedSet.tailSet(xzRectangle);
//		System.out.println(xzRectangleSortedSet);
		BidirectionalIterator<XZRectangle> it = xzRectangleSortedSet.iterator();		
		while(it.hasNext()){
			XZRectangle currentXZRectangle = it.next();
			RectangleLineRelation relation = findRelation(currentXZRectangle, yLineSegment);
			if(includeTouching){
				if(relation == RectangleLineRelation.TOUCHING || relation == RectangleLineRelation.INTERSECT){
					return intersection(currentXZRectangle, yLineSegment);
				}
			}else{
				if(relation == RectangleLineRelation.INTERSECT){
					return intersection(currentXZRectangle, yLineSegment);
				}
			}
			
		}
		return new Point(p.getX(), 0, p.getZ());
	} 
	
	public static Point projectZPositive(Point p, ObjectSortedSet<XYRectangle> xyRectangleSortedSet, boolean includeTouching, int maxZ){
		XYRectangle xyRectangle = new XYRectangle(p, 1, 1, false);
		zLineSegment zLineSegment = new zLineSegment(p, 1000, true);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xyRectangle);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();		
		while(it.hasNext()){
			XYRectangle currentXYRectangle = it.next();
			RectangleLineRelation relation = findRelation(currentXYRectangle, zLineSegment);
			if(includeTouching){
				if(relation == RectangleLineRelation.TOUCHING || relation == RectangleLineRelation.INTERSECT){
					return intersection(currentXYRectangle, zLineSegment);
				}
			}else{
				if(relation == RectangleLineRelation.INTERSECT){
					return intersection(currentXYRectangle, zLineSegment);
				}
			}
			
		}
		return new Point(p.getX(), p.getY(), maxZ);
	} 
	public static Point projectZNegative(Point p, ObjectSortedSet<XYRectangle> xyRectangleSortedSet, boolean includeTouching){
		XYRectangle xzRectangle = new XYRectangle(p, 1, 1, true);
		zLineSegment zLineSegment = new zLineSegment(p, 1000, false);
		xyRectangleSortedSet = xyRectangleSortedSet.tailSet(xzRectangle);
//		System.out.println(xyRectangleSortedSet);
		BidirectionalIterator<XYRectangle> it = xyRectangleSortedSet.iterator();		
		while(it.hasNext()){
			XYRectangle currentXYRectangle = it.next();
			RectangleLineRelation relation = findRelation(currentXYRectangle, zLineSegment);
			if(includeTouching){
				if(relation == RectangleLineRelation.TOUCHING || relation == RectangleLineRelation.INTERSECT){
					return intersection(currentXYRectangle, zLineSegment);
				}
			}else{
				if(relation == RectangleLineRelation.INTERSECT){
					return intersection(currentXYRectangle, zLineSegment);
				}
			}
			
		}
		return new Point(p.getX(), p.getY(),0);
	} 
	
	
	


	public static RectangleLineRelation findRelation(XYRectangle xyRectangle, zLineSegment zLineSegment){
		Point zLineMinPoint = zLineSegment.getStartPoint();
		Point xyPosition = xyRectangle.getPosition();
		if(xyPosition.getZ() <= zLineSegment.getEndPoint().getZ() 
				&& xyPosition.getZ() >= zLineSegment.getStartPoint().getZ()){
			
			if ((zLineMinPoint.getX() == xyPosition.getX() + xyRectangle.getXSize()
					|| zLineMinPoint.getX() == xyPosition.getX()) 
					&& zLineMinPoint.getY() <= xyPosition.getY() + xyRectangle.getYSize()
					&& zLineMinPoint.getY() >= xyPosition.getY() ){
				return RectangleLineRelation.TOUCHING;
			}else if ((zLineMinPoint.getY() == xyPosition.getY() + xyRectangle.getYSize()
					|| zLineMinPoint.getY() == xyPosition.getY()) 
					&& zLineMinPoint.getX() <= xyPosition.getX() + xyRectangle.getXSize()
					&& zLineMinPoint.getX() >= xyPosition.getX() ){
				return RectangleLineRelation.TOUCHING;
			}else if(zLineMinPoint.getX() < xyPosition.getX() + xyRectangle.getXSize()
					&& zLineMinPoint.getX() > xyPosition.getX() 
					&& zLineMinPoint.getY() < xyPosition.getY() + xyRectangle.getYSize()
					&& zLineMinPoint.getY() > xyPosition.getY()){
				return RectangleLineRelation.INTERSECT;
			} 
		}
		return RectangleLineRelation.NOTINTERSECT;
	}
	public static Point intersection(XYRectangle xyRec, zLineSegment zLineSegment){
		return new Point(zLineSegment.getStartPoint().getX(), 
				zLineSegment.getStartPoint().getY(), 
				xyRec.getPosition().getZ());		
	}
	
	public static RectangleLineRelation findRelation(XZRectangle xzRectangle, yLineSegment yLineSegment){
		Point xzPosition = xzRectangle.getPosition();
		Point yLineMinPoint = yLineSegment.getStartPoint();
		if (xzPosition.getY() <= yLineSegment.getEndPoint().getY()
				&&xzPosition.getY() >=yLineSegment.getStartPoint().getY()) {
			if((yLineMinPoint.getX() == xzPosition.getX() 
					||yLineMinPoint.getX() ==xzPosition.getX()+xzRectangle.getXSize())
					&& (yLineMinPoint.getZ() <= xzPosition.getZ() + xzRectangle.getZSize()
					&& yLineMinPoint.getZ() >= xzPosition.getZ())){
				return RectangleLineRelation.TOUCHING;
				
				
			}else if((yLineMinPoint.getZ() == xzPosition.getZ() 
					||yLineMinPoint.getZ() == xzPosition.getZ()+xzRectangle.getZSize())
					&& (yLineMinPoint.getX() <= xzPosition.getX() + xzRectangle.getXSize()
					&& yLineMinPoint.getX() >= xzPosition.getX())){
				return RectangleLineRelation.TOUCHING;
			}else if(yLineMinPoint.getX() < xzPosition.getX() + xzRectangle.getXSize()
					&& yLineMinPoint.getX() > xzPosition.getX() 
					&& yLineMinPoint.getZ() > xzPosition.getZ()
					&& yLineMinPoint.getZ() < xzPosition.getZ() + xzRectangle.getZSize()){
				return RectangleLineRelation.INTERSECT;
				
			}
			
		}
		
		
		return RectangleLineRelation.NOTINTERSECT;
	}
	public static Point intersection (XZRectangle xzRectangle , yLineSegment yLineSegment){
		
		return new Point(yLineSegment.getStartPoint().getX(),
				xzRectangle.getPosition().getY(), 
				yLineSegment.getStartPoint().getZ()); 
		
	}
	
	public static RectangleLineRelation findRelation (YZRectangle yzRectangle, xLineSegment xLineSegment){
		Point yzPosition = yzRectangle.getPosition();
		Point xLineMinPoint = xLineSegment.getStartPoint();
		if(yzPosition.getX() <= xLineSegment.getEndPoint().getX()
				&& yzPosition.getX() >= xLineSegment.getStartPoint().getX()){
			if((xLineMinPoint.getY() == yzPosition.getY()+ yzRectangle.getYSize() 
					|| xLineMinPoint.getY() == yzPosition.getY()) 
					&& xLineMinPoint.getZ() <= yzPosition.getZ()+ yzRectangle.getZSize()
					&& xLineMinPoint.getZ() >= yzPosition.getZ()){
				return RectangleLineRelation.TOUCHING;
				
			}else if((xLineMinPoint.getZ() == yzPosition.getZ()+ yzRectangle.getZSize() 
					|| xLineMinPoint.getZ() == yzPosition.getZ()) 
					&& xLineMinPoint.getY() <= yzPosition.getY()+ yzRectangle.getYSize()
					&& xLineMinPoint.getY() >= yzPosition.getY()){
				return RectangleLineRelation.TOUCHING;
				
			}else if(xLineMinPoint.getY()< yzPosition.getY() + yzRectangle.getYSize()
					&& xLineMinPoint.getY()> yzPosition.getY() 
					&& xLineMinPoint.getZ()> yzPosition.getZ()
					&& xLineMinPoint.getZ()< yzPosition.getZ()+ yzRectangle.getZSize() ){
				return RectangleLineRelation.INTERSECT;
			}
		}
		
		return RectangleLineRelation.NOTINTERSECT;
		
	}
	
	public static Point intersection (YZRectangle yzRectangle, xLineSegment xLineSegment){
		return new Point(yzRectangle.getPosition().getX(), 
				xLineSegment.getStartPoint().getY(), 
				xLineSegment.getStartPoint().getZ());
		
		
	}
	/**
	 * 
	 * @param xyRectangle
	 * @param xzRectangle
	 * @return
	 */
	
	public static RectangleRetangleRelation findRelation(XYRectangle xyRectangle,XZRectangle xzRectangle){
		yLineSegment yLine1 = xyRectangle.getYLineSegment(true);
		yLineSegment yLine2 = xyRectangle.getYLineSegment(false);
		zLineSegment zLine1=  xzRectangle.getZLineSegment(true);
		zLineSegment zLine2=  xzRectangle.getZLineSegment(false);
		
		RectangleLineRelation yLine1Relation = findRelation(xzRectangle, yLine1);
		RectangleLineRelation yLine2Relation = findRelation(xzRectangle, yLine2);
		RectangleLineRelation zLine1Relation = findRelation(xyRectangle, zLine1);
		RectangleLineRelation zLine2Relation = findRelation(xyRectangle, zLine2);
		
		
		if(yLine1Relation == RectangleLineRelation.TOUCHING 
				&& zLine2.getEndPoint().getX() >= yLine1.getStartPoint().getX()){
			return RectangleRetangleRelation.TOUCHINGPOINT;
			
		}else if(yLine2Relation == RectangleLineRelation.TOUCHING 
				&& zLine1.getEndPoint().getX() <= yLine2.getEndPoint().getX()){
			 return RectangleRetangleRelation.TOUCHINGPOINT;
		}else if(yLine1Relation == RectangleLineRelation.INTERSECT
				|| yLine2Relation == RectangleLineRelation.INTERSECT
				|| yLine1Relation == RectangleLineRelation.TOUCHING
				|| yLine2Relation == RectangleLineRelation.TOUCHING
				|| zLine1Relation == RectangleLineRelation.INTERSECT
				|| zLine2Relation == RectangleLineRelation.INTERSECT
				|| zLine1Relation == RectangleLineRelation.TOUCHING
				|| zLine2Relation == RectangleLineRelation.TOUCHING){
			return RectangleRetangleRelation.INTERSECT;
		}
		
		return RectangleRetangleRelation.NONINTERSECT;
	}
	
	public static RectangleRetangleRelation findRelation(XYRectangle xyRectangle, YZRectangle yzRectangle){
		xLineSegment xLineSegment1 = xyRectangle.getXLineSegment(true);
		xLineSegment xLineSegment2 = xyRectangle.getXLineSegment(false);
		zLineSegment zLineSegment1 = yzRectangle.getZLineSegment(true);
		zLineSegment zLineSegment2 = yzRectangle.getZLineSegment(false);
		
		RectangleLineRelation xLine1Relation = findRelation(yzRectangle, xLineSegment1);
		RectangleLineRelation xLine2Relation = findRelation(yzRectangle, xLineSegment2);
		
		RectangleLineRelation zLine1Relation = findRelation(xyRectangle, zLineSegment1);
		RectangleLineRelation zLine2Relation = findRelation(xyRectangle, zLineSegment2);
		
		
		if(zLine1Relation == RectangleLineRelation.TOUCHING
				 && zLineSegment1.getEndPoint().getY() <= xLineSegment2.getEndPoint().getY()){
			return RectangleRetangleRelation.TOUCHINGPOINT;
		}else if(zLine2Relation == RectangleLineRelation.TOUCHING
				&& zLineSegment2.getEndPoint().getY() >= xLineSegment1.getEndPoint().getY()){
			return RectangleRetangleRelation.TOUCHINGPOINT;
			
		}else if(xLine1Relation == RectangleLineRelation.INTERSECT
				|| xLine1Relation == RectangleLineRelation.TOUCHING
				|| xLine2Relation == RectangleLineRelation.INTERSECT
				|| xLine2Relation == RectangleLineRelation.TOUCHING
				|| zLine1Relation == RectangleLineRelation.INTERSECT
				|| zLine1Relation == RectangleLineRelation.TOUCHING
				|| zLine2Relation == RectangleLineRelation.INTERSECT
				|| zLine2Relation == RectangleLineRelation.TOUCHING){
			
		}
		return RectangleRetangleRelation.NONINTERSECT;
		
		
		
		
	}
	
	public static RectangleRetangleRelation findRelation(XZRectangle xzRectangle, YZRectangle yzRectangle){
		xLineSegment xLineSegment1 = xzRectangle.getXLineSegment(true);
		xLineSegment xLineSegment2 = xzRectangle.getXLineSegment(false);
		yLineSegment yLineSegment1 = yzRectangle.getYLineSegment(true);
		yLineSegment yLineSegment2 = yzRectangle.getYLineSegment(false);
		
		RectangleLineRelation xLine1Relation = findRelation(yzRectangle, xLineSegment1);
		RectangleLineRelation xLine2Relation = findRelation(yzRectangle, xLineSegment2);
		RectangleLineRelation yLine1Relation = findRelation(xzRectangle, yLineSegment1);
		RectangleLineRelation yLine2Relation = findRelation(xzRectangle, yLineSegment2);
		
		if(yLine1Relation ==  RectangleLineRelation.TOUCHING
				&& yLineSegment1.getEndPoint().getZ()<= xLineSegment2.getEndPoint().getZ()){
			return RectangleRetangleRelation.TOUCHINGPOINT;
		}else if(yLine2Relation ==  RectangleLineRelation.TOUCHING
				&& yLineSegment2.getEndPoint().getZ()>= xLineSegment1.getEndPoint().getZ()){
			return RectangleRetangleRelation.TOUCHINGPOINT;
		}else if(xLine1Relation == RectangleLineRelation.INTERSECT
				|| xLine1Relation == RectangleLineRelation.TOUCHING
				|| xLine2Relation == RectangleLineRelation.INTERSECT
				|| xLine2Relation == RectangleLineRelation.TOUCHING
				|| yLine1Relation == RectangleLineRelation.INTERSECT
				|| yLine1Relation == RectangleLineRelation.TOUCHING
				|| yLine2Relation == RectangleLineRelation.INTERSECT
				|| yLine2Relation == RectangleLineRelation.TOUCHING){
			return RectangleRetangleRelation.INTERSECT; 
			
		}
		
		
		return RectangleRetangleRelation.NONINTERSECT;
		
	}
	
	public static yLineSegment intersection (XYRectangle xyRectangle , YZRectangle yzRectangle){
		zLineSegment zLineSegment1 = yzRectangle.getZLineSegment(true);
		zLineSegment zLineSegment2 = yzRectangle.getZLineSegment(false);
		RectangleLineRelation zLineRelation1 = findRelation(xyRectangle, zLineSegment1);
		RectangleLineRelation zLineRelation2 = findRelation(xyRectangle, zLineSegment2);
		if(zLineRelation1 == RectangleLineRelation.INTERSECT 
				&& zLineRelation1 == RectangleLineRelation.TOUCHING){
			if(zLineRelation2 == RectangleLineRelation.INTERSECT
					&& zLineRelation2 == RectangleLineRelation.TOUCHING){
				Point point1 = intersection(xyRectangle, zLineSegment1);
				Point point2 = intersection(xyRectangle, zLineSegment2);
				return new yLineSegment(point1, point2);
				
			}else{
				
				xLineSegment xLineSegment2 = xyRectangle.getXLineSegment(false);
				Point point1 = intersection(yzRectangle, xLineSegment2 );
				Point point2 = intersection(xyRectangle, zLineSegment1);
				return new yLineSegment(point1, point2);
				
			}
		}else if(zLineRelation2 == RectangleLineRelation.INTERSECT 
				&& zLineRelation2 == RectangleLineRelation.TOUCHING){
			if(zLineRelation1 == RectangleLineRelation.INTERSECT 
					&& zLineRelation1 == RectangleLineRelation.TOUCHING){
				Point point1 = intersection(xyRectangle, zLineSegment1);
				Point point2 = intersection(xyRectangle, zLineSegment2);
				return new yLineSegment(point1, point2);
			}else{
				xLineSegment xLineSegment1 = xyRectangle.getXLineSegment(true);
				Point point1 = intersection(yzRectangle, xLineSegment1 );
				Point point2 = intersection(xyRectangle, zLineSegment2);
				return new yLineSegment(point1, point2);
			}
		}else{
			xLineSegment xLineSegment1 = xyRectangle.getXLineSegment(true);
			xLineSegment xLineSegment2 = xyRectangle.getXLineSegment(false);
			Point point1 = intersection(yzRectangle, xLineSegment1 );
			Point point2 = intersection(yzRectangle, xLineSegment2);
			return new yLineSegment(point1, point2);
			
			
		}

		
	}
	
	public static xLineSegment intersection(XYRectangle xyRectangle , XZRectangle xzRectangle){
		yLineSegment yLineSegment1 = xyRectangle.getYLineSegment(true);
		yLineSegment yLineSegment2 = xyRectangle.getYLineSegment(false);
		RectangleLineRelation yLineRelation1 = findRelation(xzRectangle, yLineSegment1);
		RectangleLineRelation yLineRelation2 = findRelation(xzRectangle, yLineSegment2);
		if(yLineRelation1 == RectangleLineRelation.INTERSECT 
				|| yLineRelation1 == RectangleLineRelation.TOUCHING){
			if(yLineRelation2 == RectangleLineRelation.TOUCHING
					|| yLineRelation2 == RectangleLineRelation.INTERSECT){
				Point point1 = intersection(xzRectangle, yLineSegment1);
				Point point2 = intersection(xzRectangle, yLineSegment2);
				return new xLineSegment(point1, point2);
				
				
			}else{
				zLineSegment zLineSegment2 = xzRectangle.getZLineSegment(false);
				Point point1 = intersection(xzRectangle, yLineSegment1);
				Point point2 = intersection(xyRectangle, zLineSegment2);
				return new xLineSegment(point1, point2);
				
				
			}
		}else if(yLineRelation2 == RectangleLineRelation.INTERSECT 
				|| yLineRelation2 == RectangleLineRelation.TOUCHING){
			if(yLineRelation1 == RectangleLineRelation.INTERSECT 
					|| yLineRelation1 == RectangleLineRelation.TOUCHING){
				Point point1 = intersection(xzRectangle, yLineSegment1);
				Point point2 = intersection(xzRectangle, yLineSegment2);
				return new xLineSegment(point1, point2);
			}else{
				zLineSegment zLineSegment1 = xzRectangle.getZLineSegment(true);
				Point point1 = intersection(xzRectangle, yLineSegment2);
				Point point2 = intersection(xyRectangle, zLineSegment1);
				return new xLineSegment(point1, point2);
			}
			
		}else{
			zLineSegment zLineSegment1 = xzRectangle.getZLineSegment(true);
			zLineSegment zLineSegment2 = xzRectangle.getZLineSegment(false);
			Point point1 = intersection(xyRectangle, zLineSegment2);
			Point point2 = intersection(xyRectangle, zLineSegment1);
			return new xLineSegment(point1, point2);
		}
		
	}
	/**
	 * return the zline intersection 
	 * @param xzRectangle
	 * @param yzRectangle
	 * @return
	 */
	public static zLineSegment intersection(XZRectangle xzRectangle, YZRectangle yzRectangle){
		
		xLineSegment xLineSegment1 = xzRectangle.getXLineSegment(true);
		xLineSegment xLineSegment2 = xzRectangle.getXLineSegment(false);
		RectangleLineRelation xLineRelation1 = findRelation(yzRectangle, xLineSegment1);
		RectangleLineRelation xLineRelation2 = findRelation(yzRectangle, xLineSegment2);
		if(xLineRelation1 == RectangleLineRelation.INTERSECT
				|| xLineRelation1 == RectangleLineRelation.TOUCHING){

			if(xLineRelation2 ==RectangleLineRelation.INTERSECT
					||xLineRelation2 == RectangleLineRelation.TOUCHING){
			
				Point point1 = intersection(yzRectangle, xLineSegment1);
				Point point2 = intersection(yzRectangle, xLineSegment2);
				return new zLineSegment(point1, point2);
			}else{
				yLineSegment yLineSegment2 = yzRectangle.getYLineSegment(false);
				Point point1 = intersection(yzRectangle, xLineSegment1);
				Point point2 = intersection(xzRectangle, yLineSegment2);
				return new zLineSegment(point1, point2);
				
			}
		}else if(xLineRelation2 ==RectangleLineRelation.INTERSECT
				||xLineRelation2 == RectangleLineRelation.TOUCHING){
			if(xLineRelation1 == RectangleLineRelation.INTERSECT
					|| xLineRelation1 == RectangleLineRelation.TOUCHING){
				Point point1 = intersection(yzRectangle, xLineSegment1);
				Point point2 = intersection(yzRectangle, xLineSegment2);
				return new zLineSegment(point1, point2);
			}else{
				yLineSegment yLineSegment1 = yzRectangle.getYLineSegment(true);
				Point point1 = intersection(yzRectangle, xLineSegment2);
				Point point2 = intersection(xzRectangle, yLineSegment1);
				return new zLineSegment(point1, point2);
			}
			
		}else{
			yLineSegment yLineSegment1 = yzRectangle.getYLineSegment(true);
			yLineSegment yLineSegment2 = yzRectangle.getYLineSegment(false);
			Point point1 = intersection(xzRectangle, yLineSegment2);
			Point point2 = intersection(xzRectangle, yLineSegment1);
			return new zLineSegment(point1, point2);
		}
		
		
	}
	public static ObjectSortedSet<xLineSegment> intersection(XZRectangle xzRectangle,ObjectSortedSet<XYRectangle> xyObjectNegativeSortedSet, boolean yIncreased){

//		Point p=  new Point(xyRectangle.getMaxX(), xyRectangle.getMaxY(), xyRectangle.getPosition().getZ());
//		XYRectangle xyRectangle1 = new XYRectangle(p, 1, 1, false);
//		XZRectangle tempRectangle = new XZRectangle(, xSize, zSize, isPositiveFaced)
		
		ObjectSortedSet<xLineSegment> xLineSortedSet = new ObjectRBTreeSet<xLineSegment>(new xLimeSegmentComparator());
		Point p = new Point(xzRectangle.getMaxX(), xzRectangle.getPosition().getY(), xzRectangle.getPosition().getZ());
		
		XYRectangle seperateRectangle= new XYRectangle(p,1, 1, false) ;
		XZRectangle tempRectangle = null;
		if(yIncreased){
			Point tempPoint = new Point(xzRectangle.getPosition().getX(),xzRectangle.getPosition().getY()+1,xzRectangle.getPosition().getZ());
			tempRectangle = new XZRectangle(tempPoint,xzRectangle.getXSize(), xzRectangle.getZSize(), xzRectangle.isPositiveFace());
			
		}else{
			tempRectangle = xzRectangle;
		}
		
		xyObjectNegativeSortedSet= xyObjectNegativeSortedSet.tailSet(seperateRectangle);
		
		for(XYRectangle currentXYRectangle : xyObjectNegativeSortedSet){
			RectangleRetangleRelation relation  = GeometricOperator.findRelation(currentXYRectangle, tempRectangle);
			
				if(relation == RectangleRetangleRelation.INTERSECT){
					
					xLineSegment tempXLine = GeometricOperator.intersection(currentXYRectangle, xzRectangle);
					xLineSortedSet.add(tempXLine);
				}
			
			
		}
		
		
		return xLineSortedSet;
		
		
	}
	
	
}
////	
//	public static YZRectangle getOverlaped(YZRectangle yzRectangle1, YZRectangle yzRectangle2){
//		
//		
//		
//		return null;
//		
//	}
	


//public static boolean [] [] toArray(Rectangle2D rectangle2d){
//boolean [][] result = new boolean [(int)rectangle2d.getMaxX()][(int)rectangle2d.getMaxY()];
//for (int i = (int)rectangle2d.getMinX(); i < (int)rectangle2d.getMaxX(); i++) {
//	for (int j = (int)rectangle2d.getMinY(); j < (int)rectangle2d.getMaxY(); j++) {
//		result[i][j] = true;
//		
//	}
//}
//
//return result;
//}
//
//public static boolean [][] toArray (Rectangle2D projectedRectangle2d , List<Rectangle2D> rectangle2dList){
//boolean [][] result = new boolean [(int)projectedRectangle2d.getMaxX()][(int)projectedRectangle2d.getMaxY()];
//for(Rectangle2D currentRectangle2d : rectangle2dList){
//	
//
//	
//}
//
//
//
////		int maxX = 0;
////int maxY = 0;
////for (Rectangle2D currentRectangle2d : rectangle2dList) {
////	if(currentRectangle2d.getMaxX() > maxX)maxX= (int)currentRectangle2d.getMaxX(); 
////	if(currentRectangle2d.getMaxY() > maxY)maxY= (int)currentRectangle2d.getMaxY();
////				
////}
////boolean [][] result = new boolean [maxX][maxY];
////for (Rectangle2D currentRectangle2d : rectangle2dList) {
////	for (int i = (int)currentRectangle2d.getMinX(); i < (int)currentRectangle2d.getMaxX(); i++) {
////		for (int j = (int)currentRectangle2d.getMinY(); j < (int)currentRectangle2d.getMaxY(); j++) {
////			result[i][j] = true;
////			
////		}
////	}
////				
////}
//return result;
//
//
//}
